package com.caiyigo.baihua.fetion;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Pattern;

import javax.swing.JOptionPane;

import net.solosky.maplefetion.ClientState;
import net.solosky.maplefetion.FetionClient;
import net.solosky.maplefetion.LoginState;
import net.solosky.maplefetion.NotifyEventAdapter;
import net.solosky.maplefetion.bean.Buddy;
import net.solosky.maplefetion.bean.Cord;
import net.solosky.maplefetion.bean.Group;
import net.solosky.maplefetion.bean.Member;
import net.solosky.maplefetion.bean.Message;
import net.solosky.maplefetion.bean.Presence;
import net.solosky.maplefetion.bean.Relation;
import net.solosky.maplefetion.bean.VerifyImage;
import net.solosky.maplefetion.client.dialog.ChatDialogProxy;
import net.solosky.maplefetion.client.dialog.GroupDialog;
import net.solosky.maplefetion.event.notify.ImageVerifyEvent;
import net.solosky.maplefetion.net.AutoTransferFactory;
import net.solosky.maplefetion.store.FetionStore;
import net.solosky.maplefetion.store.SimpleFetionStore;
import net.solosky.maplefetion.util.SingleExecutor;
import net.solosky.maplefetion.util.ThreadTimer;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;

import com.caiyigo.baihua.entity.CjBean;
import com.caiyigo.baihua.entity.Xuesheng;

public class FetionClients extends NotifyEventAdapter {
	private static Logger logger = Logger.getLogger(FetionClients.class);
	private FetionClient client;
	private ImageVerifyEvent verifyEvent;
	private String serviceId;
	private String type;
	private String pici;
	private Map<String, String> messageMap;
	private static List<Xuesheng> xueshengsList;
	private static Map<String, Xuesheng> xueshengMapKeyAtZkz;
	private static Map<String, Xuesheng> xueshengMapKeyAtMobile;
	private static List<String> buddyMessage = new ArrayList<String>();

	public FetionClients(String serviceId, String pass) {
		this.serviceId = serviceId;
		this.client = new FetionClient(serviceId, pass, this,
				new AutoTransferFactory(), new SimpleFetionStore(),
				new ThreadTimer(), new SingleExecutor());
		xueshengsList = XueshengMap.getInstance(serviceId).getXueshengList();
		xueshengMapKeyAtZkz = XueshengMap.getInstance(serviceId)
				.getXueshengMapKeyAtZkz();
		xueshengMapKeyAtMobile = XueshengMap.getInstance(serviceId)
				.getXueshengMapKeyAtMobile();
	}

	public void login(int presence) {
		this.client.enableGroup(false);
		this.client.login(presence);
	}

	public void getMessageMap() {
		if (StringUtils.TypeValues.ZW.equals(type)) {
			messageMap = new FetionApplication().getDbService().getZwList(pici,
					serviceId, message, xueshengMapKeyAtZkz);
		} else if (StringUtils.TypeValues.CJ.equals(type)) {
			messageMap = new FetionApplication().getDbService().getCjList(pici,
					serviceId, message, xueshengMapKeyAtZkz);
		} else if (StringUtils.TypeValues.ZDY.equals(type)) {
			messageMap = new FetionApplication().getDbService().getZdyList(
					serviceId, message, xueshengsList);
		}

	}

	public void tel(String message, String type, String pici) throws Exception {
		this.type = type;
		this.pici = pici;
		this.message = message;
		getMessageMap();
		if (preViewAndIsContune()) {
			enableButton(false);
		} else {
			return;
		}
		if (client.getState() == ClientState.ONLINE) {
			ExecutorService executor = (ExecutorService) Executors
					.newFixedThreadPool(7);
			List<SendFetion> taskList = new ArrayList<SendFetion>();
			for (String mobile : messageMap.keySet()) {
				SendFetion task = new SendFetion(client, mobile,
						messageMap.get(mobile), xueshengMapKeyAtMobile);
				taskList.add(task);
			}
			List<Future<Result>> resultList = null;
			try {
				resultList = executor.invokeAll(taskList);
			} catch (InterruptedException e) {
				logger.warn(e.getMessage());
				JOptionPane.showMessageDialog(null, "任务失败，请不要再执行");
			}
			executor.shutdown();
			System.out.println("打印结果：");
			try {
				writeToFile(resultList, type, serviceId);
			} catch (Exception e) {
				updateHelpMessage("\n" + "写入文件出错...");
			}
			try {
				new FetionApplication().getDbService().updateSend(resultList,
						StringUtils.TypeValues.ZW == type, pici,xueshengMapKeyAtZkz);
			} catch (Exception e) {
				logger.warn(e.getMessage());
				JOptionPane.showMessageDialog(null, "任务失败，请不要再执行");
			}
			enableButton(true);
		}
	}

	public void verify(String code) {
		if (this.verifyEvent != null) {
			this.verifyEvent.getVerifyImage().setVerifyCode(code);
			this.client.processVerify(this.verifyEvent);
			this.verifyEvent = null;
		} else {
			System.out.println("No verify action to do.");
		}
	}

	@Override
	public void loginStateChanged(LoginState state) {
		switch (state) {
		case SEETING_LOAD_DOING: // 加载自适应配置
			updateHelpMessage("\n" + "获取自适应系统配置...");

			break;
		case SSI_SIGN_IN_DOING: // SSI登录
			updateHelpMessage("\n" + "SSI登录...");

			break;
		case SIPC_REGISTER_DOING: // 注册SIPC服务器
			updateHelpMessage("\n" + "服务器验证...");

			break;
		case GET_CONTACTS_INFO_DOING: // 获取联系人信息
			updateHelpMessage("\n" + "获取联系人...");
			break;
		case GET_GROUPS_INFO_DOING: // 获取群消息
			updateHelpMessage("\n" + "获取群信息...");

			break;
		case GROUPS_REGISTER_DOING: // 注册群
			updateHelpMessage("\n" + "群登录...");

			break;

		// 以下是成功信息，不提示
		case SETTING_LOAD_SUCCESS:
		case SSI_SIGN_IN_SUCCESS:
		case SIPC_REGISGER_SUCCESS:
		case GET_CONTACTS_INFO_SUCCESS:
		case GET_GROUPS_INFO_SUCCESS:
		case GROUPS_REGISTER_SUCCESS:
			break;

		case LOGIN_SUCCESS:
			updateHelpMessage("\n" + "登录成功");

			enableButton(true);
			this.loginSuccess();
			break;

		case SSI_NEED_VERIFY:
		case SSI_VERIFY_FAIL:
			if (state == LoginState.SSI_NEED_VERIFY) {
				updateHelpMessage("\n" + "需要验证, 请输入目录下的[verify.png]里面的验证码:");

			} else {
				updateHelpMessage("\n" + "验证码验证失败，刷新验证码中...");

			}
			break;

		case SSI_CONNECT_FAIL:
			updateHelpMessage("\n" + "SSI连接失败!");

			break;

		case SIPC_TIMEOUT:
			updateHelpMessage("\n" + "登陆超时！");

			break;

		case SSI_AUTH_FAIL:
			updateHelpMessage("\n" + "用户名或者密码错误!");

			break;

		case SSI_ACCOUNT_SUSPEND:
			updateHelpMessage("\n" + "你已经停机，请缴费后再使用飞信。");

			break;

		default:
			updateHelpMessage("\n" + "其他状态:" + state.name());
			break;
		}

	}

	@Override
	protected void imageVerify(final VerifyImage verifyImage,
			final String verifyReason, final String verifyTips,
			final ImageVerifyEvent event) {

		String fileName = saveImage(verifyImage.getImageData());

		if (client.getState() == ClientState.LOGGING) {
			updateHelpMessage("当前登录过程需要验证，原因【" + verifyReason
					+ "】,请输入当前目录下图片[verify.jpg]中的验证码：");

			String line = fetion.getCode(fileName);
			verifyImage.setVerifyCode(line);
			client.processVerify(event);
		} else {
			fetion.helpMessage
					.append("当前操作需要验证,原因:【"
							+ verifyReason
							+ "】。\n请使用verify命令输入当前目录下图片[verify.jpg]中的验证码(如verify 123abc).");

			this.verifyEvent = event;

		}
	}

	/**
	 * 保存验证图片
	 * 
	 * @param img
	 */
	private String saveImage(byte[] img) {
		String baseDir = "c:/baihuaimages/";
		String fileName = baseDir + String.valueOf(new Date().getTime())
				+ ".png";
		try {
			File file2 = new File(baseDir);
			if (!file2.exists() && !file2.isDirectory()) {
				file2.mkdir();
			}
			File f = new File(fileName);
			if (!f.exists()) {
				f.createNewFile();
			}
			FileOutputStream out = new FileOutputStream(f);
			out.write(img);
			out.close();
		} catch (Exception e) {
		}
		return fileName;
	}

	public static String fomartString(String str, int len) {
		if (str != null) {
			if (str.length() > len)
				return str.substring(0, len) + ".";
			else
				return str;
		} else {
			return "";
		}
	}

	/**
	 * 格式化关系
	 */
	public static String formatRelation(Relation relation) {
		switch (relation) {
		case BUDDY:
			return "B";
		case UNCONFIRMED:
			return "W";
		case DECLINED:
			return "X";
		case STRANGER:
			return "？";
		case BANNED:
			return "@";
		default:
			return "-";
		}

	}

	public static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		return pattern.matcher(str).matches();
	}

	public static String getNowTime() {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
		return dateFormat.format(date);
	}

	public boolean preViewAndIsContune() {
		Integer flag = 5;
		if (null != messageMap && messageMap.size() > 0) {
			String s = messageMap.get(messageMap.keySet().iterator().next());
			Integer len = s.length() / 2;
			String s1 = s.substring(0, len);
			String s2 = s.substring(len, s.length());
			flag = JOptionPane.showConfirmDialog(null, s1 + "\n" + s2, "发送预览",
					JOptionPane.YES_NO_OPTION);

		} else {
			JOptionPane.showMessageDialog(null, "没有该批次的资料，请检查所属号码或者退出再试");
		}
		return 0 == flag;
	}

	public static void writeToFile(List<Future<Result>> resultList,
			String type, String serviceId) throws IOException {
		String baseDir = "c:/baihuaimages/";
		String fileName = "";
		if (StringUtils.TypeValues.ZW.equals(type)) {
			fileName = baseDir + "座位" + getNowTime() + ".txt";
		} else if (StringUtils.TypeValues.CJ.equals(type)) {
			fileName = baseDir + "成绩" + getNowTime() + ".txt";
		} else if (StringUtils.TypeValues.ZDY.equals(type)) {
			fileName = baseDir + "自定义消息" + getNowTime() + ".txt";
		} else {
			fileName = baseDir + getNowTime() + ".txt";
		}

		File file = new File(fileName);
		File file2 = new File(baseDir);
		if (!file2.exists() && !file2.isDirectory()) {
			file2.mkdir();
		}
		if (!file.exists()) {
			file.createNewFile();
		}

		StringBuffer buffer = new StringBuffer();
		buffer.append("共发送" + resultList.size() + ",列表如下:");
		buffer.append(System.getProperty("line.separator"));
		Collections.sort(resultList, new Comparator<Future<Result>>() {
			@Override
			public int compare(Future<Result> o1, Future<Result> o2) {
				Result result1 = null;
				Result result2 = null;
				try {
					result1 = o1.get();
					result2 = o2.get();
					if (null == result1 || null == result2) {
						return -1;
					}
					return result1.getOrder().compareTo(result2.getOrder());
				} catch (InterruptedException e) {
					logger.warn("写入文件出错", e.getCause());
					return -1;
				} catch (ExecutionException e) {
					logger.warn("写入文件出错", e.getCause());
					return -1;
				}


			}
		});
		
		for (int i = 0; i < resultList.size(); i++) {
			Future<Result> future = resultList.get(i);
			try {
				Result result = future.get();
				if (null == result) {
					continue;
				}
				String name = XueshengMap.getInstance(serviceId)
						.getXueshengMapKeyAtMobile().get(result.getMobile())
						.getXsXm();
				buffer.append(StringUtils.buildIndex(i)
						+ "--"
						+ (null == name ? "" : StringUtils.getFullName(name,
								false)) + "--" + result.getMobile() + "--"
						+ StringUtils.formatYuanyin(result.getResult()));
				buffer.append(System.getProperty("line.separator"));

			} catch (InterruptedException e) {
				logger.warn("拼凑姓名出错", e.getCause());
				continue;
			} catch (ExecutionException e) {
				logger.warn("拼凑姓名出错", e.getCause());
				continue;
			}
		}
		buffer.append("----------以下是好友消息-----------");
		buffer.append(System.getProperty("line.separator"));
		for (String string : buddyMessage) {
			buffer.append(string);
			buffer.append(System.getProperty("line.separator"));
		}
		try {
			org.apache.commons.io.FileUtils.writeStringToFile(file,
					buffer.toString(), "GBK");
		} catch (IOException e) {
			e.printStackTrace();
		}
		Runtime.getRuntime().exec("notepad " + fileName);

	}

	public static void enableButton(boolean flag) {
		fetion.jbSendCJ.setEnabled(flag);
		fetion.jbSendZDY.setEnabled(flag);
		fetion.jbSendZW.setEnabled(flag);
	}

	/**
	 * 登录成功之后，启动主循环
	 */
	public void loginSuccess() {

		Runnable r = new Runnable() {
			public void run() {
				try {

					my();
					list();

				} catch (Exception e) {
					updateHelpMessage("\n" + "程序运行出错");

					e.printStackTrace();
					if (client.getState() == ClientState.ONLINE) {
						client.logout();
					}
				}
			}
		};

		Thread t = new Thread(r);
		t.setName("MapleFetionConsoleReaderThead");

		t.start();

	}

	/**
	 * 输出用户自己信息
	 */
	public void my() {

		updateHelpMessage("\n" + "你好，"
				+ client.getFetionUser().getDisplayName() + "! - ["
				+ client.getFetionUser().getImpresa() + "]");

	}

	/**
	 * 显示所有用户列表
	 */
	public void list() {
		updateHelpMessage("\n" + "\n=================================");

		updateHelpMessage("\n" + "所有好友列表");

		updateHelpMessage("\n" + "-------------------------------");

		updateHelpMessage("\n" + "#ID\t好友昵称\t在线状态\t个性签名");

		FetionStore store = this.client.getFetionStore();
		Iterator<Cord> it = store.getCordList().iterator();
		int id = 0;

		// 分组显示好友
		while (it.hasNext()) {
			Cord cord = it.next();
			id = cord(cord.getId(), cord.getTitle(), id,
					store.getBuddyListByCord(cord));
		}
		id = cord(-1, "默认分组", id, store.getBuddyListWithoutCord());
	}

	/**
	 * 显示一个组的用户
	 */
	public int cord(int cordId, String name, int startId,
			Collection<Buddy> buddyList) {
		Iterator<Buddy> it = buddyList.iterator();
		Buddy buddy = null;
		updateHelpMessage("\n" + "\n-------------------------------");

		updateHelpMessage("\n" + "【" + cordId + "::" + name + "】");

		updateHelpMessage("\n" + "-------------------------------");

		if (buddyList.size() == 0) {
			updateHelpMessage("\n" + "暂无好友。。");

		}
		while (it.hasNext()) {
			buddy = it.next();
			String impresa = buddy.getImpresa();
			updateHelpMessage("\n" + Integer.toString(startId) + " "
					+ formatRelation(buddy.getRelation()) + " "
					+ fomartString(buddy.getDisplayName(), 10) + "\t"
					+ buddy.getDisplayPresence() + "\t"
					+ (impresa == null ? "" : impresa));

			startId++;

		}
		return startId;
	}

	/**
	 * 接受到系统消息
	 */
	@Override
	public void systemMessageRecived(String m) {
		updateHelpMessage("\n" + "[系统消息]:" + m);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.solosky.maplefetion.NotifyListener#buddyApplication(net.solosky.
	 * maplefetion.bean.Buddy, java.lang.String)
	 */
	@Override
	public void buddyApplication(Buddy buddy, String desc) {
		updateHelpMessage("\n" + "[好友请求]:" + desc
				+ " 想加你为好友。请输入 【agree/decline 好友编号】 同意/拒绝添加请求。");

		buddyMessage.add("[好友请求]:" + desc
				+ " 想加你为好友。请输入 【agree/decline 好友编号】 同意/拒绝添加请求。");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.solosky.maplefetion.NotifyListener#buddyConfirmed(net.solosky.maplefetion
	 * .bean.Buddy, boolean)
	 */
	@Override
	public void buddyConfirmed(Buddy buddy, boolean isAgreed) {
		if (isAgreed) {
			updateHelpMessage("\n" + "[系统通知]:" + buddy.getDisplayName()
					+ " 同意了你的好友请求。");

		} else {
			updateHelpMessage("\n" + "[系统通知]:" + buddy.getDisplayName()
					+ " 拒绝了你的好友请求。");

		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.solosky.maplefetion.NotifyListener#buddyMessageRecived(net.solosky
	 * .maplefetion.bean.Buddy, java.lang.String,
	 * net.solosky.maplefetion.client.dialog.ChatDialog)
	 */
	@Override
	public void buddyMessageRecived(Buddy from, Message message,
			ChatDialogProxy dialog) {
		if (from.getRelation() == Relation.BUDDY) {
			updateHelpMessage("\n" + "[好友消息]" + from.getDisplayName() + " 说:"
					+ message.getText()
					+ "\n----------------------------------------------");

			buddyMessage.add("[好友消息]" + from.getDisplayName() + " 说:"
					+ message.getText() + "\n");
		} else {
			updateHelpMessage("\n" + "[陌生人消息]" + from.getDisplayName() + " 说:"
					+ message.getText()
					+ "\n--------------------------------------------");

			buddyMessage.add("[陌生人消息]" + from.getDisplayName() + " 说:"
					+ message.getText());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.solosky.maplefetion.NotifyListener#presenceChanged(net.solosky.
	 * maplefetion.bean.Buddy)
	 */
	@Override
	public void buddyPresenceChanged(Buddy b) {
		if (b.getPresence().getValue() == Presence.ONLINE) {
			updateHelpMessage("\n" + "[系统通知]:" + b.getDisplayName() + " 上线了。");

		} else if (b.getPresence().getValue() == Presence.OFFLINE) {
			updateHelpMessage("\n" + "[系统通知]:" + b.getDisplayName() + " 下线了。");

		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.solosky.maplefetion.NotifyListener#groupMessageRecived(net.solosky
	 * .maplefetion.bean.Group, net.solosky.maplefetion.bean.Member,
	 * java.lang.String, net.solosky.maplefetion.client.dialog.GroupDialog)
	 */
	@Override
	public void groupMessageRecived(Group group, Member from, Message message,
			GroupDialog dialog) {
		updateHelpMessage("\n" + "[群消息] 群 " + group.getName() + " 里的 "
				+ from.getDisplayName() + " 说：" + message.getText());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.solosky.maplefetion.NotifyListener#statusChanged(ClientState)
	 */
	@Override
	public void clientStateChanged(ClientState state) {
		switch (state) {
		case OTHER_LOGIN:
			JOptionPane.showMessageDialog(null, "你已经从其他客户端登录。30秒之后重新登录..");
			updateHelpMessage("\n" + "你已经从其他客户端登录。");

			updateHelpMessage("\n" + "30秒之后重新登录..");

			// //新建一个线程等待登录，不能在这个回调函数里做同步操作
			new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(30000);
					} catch (InterruptedException e) {
						updateHelpMessage("\n" + "重新登录等待过程被中断");

					}
					client.login();
				}
			}).start();
			break;
		case CONNECTION_ERROR:
			updateHelpMessage("\n" + "客户端连接异常");

			break;
		case DISCONNECTED:
			updateHelpMessage("\n" + "服务器关闭了连接");

			break;
		case LOGOUT:
			updateHelpMessage("\n" + "已经退出。。");

			break;
		case ONLINE:
			updateHelpMessage("\n" + "当前是在线状态。");

			break;

		default:
			break;
		}
	}

	private void updateHelpMessage(String string) {
		fetion.helpMessage.append(string);
		fetion.taInfo.setText(fetion.helpMessage.toString());
		fetion.taInfo.setCaretPosition(fetion.taInfo.getDocument().getLength());
	}

	private String message;

}
